package com.travel.util;
import org.apache.commons.lang3.StringUtils;
import org.bytedeco.javacv.FFmpegFrameGrabber;
import org.bytedeco.javacv.Java2DFrameConverter;
import org.bytedeco.javacv.Frame;



import javax.imageio.ImageIO;
//import java.awt.*;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.util.ArrayList;
import java.util.Collections;


/**
 * 视频取帧，可设置间隔秒数或获取所有帧数
 */
public class FetchVideoFrameUtil {

    /**
     * 获取指定视频的帧并保存为图片至指定目录
     * @param file    源视频文件
     * @param picPath 截取帧的图片存放路径
     * @throws Exception
     */
    public static void fetchPic(File file, String picPath) throws Exception {

        FFmpegFrameGrabber ff = new FFmpegFrameGrabber(file); // 获取视频文件
        System.out.println("视频总长度 " + FetchVideoFrameUtil.getVideoTime(file)); // 显示视频长度（秒/s）
        if (FetchVideoFrameUtil.getVideoTime(file) == 0){
            System.out.println("该视频文件已经损毁，无法播放");
        }

        ff.start(); // 调用视频文件播放
        int length = ff.getLengthInAudioFrames(); //视频帧数长度
        int second = (int) ff.getFrameRate();
        System.out.println("视频帧数长度 " + ff.getFrameRate());

        int i = 0; // 图片帧数，如需跳过前几秒，则在下方过滤即可
        Frame frame = null;
//        int count = 0;
        int count = second;
        while (i < length) {
            frame = ff.grabImage(); // 获取该帧图片流
//            System.out.print(i + ",");
            if (i >= second && frame != null && frame.image != null) {
//                System.out.println(i);
                writeToFile(frame, picPath, count, second); // 生成帧图片
                count++;
            }
            i++;
        }
        ff.stop();
    }

    /**
     * 截取到的帧图片写入指定文件夹
     *
     * @param frame   // 视频文件对象
     * @param picPath // 图片存放路径
     * @param count   // 当前取到第几帧
     * @param second  // 每隔多少帧取一张，一般高清视频每秒 20-24 帧，根据情况配置，如果全部提取，则将second设为 0 即可
     */
    public static void writeToFile(Frame frame, String picPath, int count, int second) {

        //创建不同的文件夹目录
        File file = new File(picPath);

        //判断文件夹是否存在
        if (!file.exists()) {
            //如果文件夹不存在，则创建新的的文件夹
            file.mkdirs();
        }

        if (second == 0) {
            // 跳过间隔取帧判断
        } else if (count % second != 0) { // 提取倍数，如每秒取一张，则： second = 20
            return;
        }
        int num = FetchVideoFrameUtil.getFileName(file,count / second);
        String fileName = "1-" + num + ".jpg";//图片命名
        File targetFile = new File(picPath + fileName);

        String imgSuffix = "jpg";

        Java2DFrameConverter converter = new Java2DFrameConverter();
        BufferedImage srcBi = converter.getBufferedImage(frame);
        int owidth = srcBi.getWidth();
        int oheight = srcBi.getHeight();
        // 对截取的帧进行等比例缩放
        int width = 800;
        int height = (int) (((double) width / owidth) * oheight);
        BufferedImage bi = new BufferedImage(width, height, BufferedImage.TYPE_3BYTE_BGR);
        bi.getGraphics().drawImage(srcBi.getScaledInstance(width, height, Image.SCALE_SMOOTH), 0, 0, null);
        try {
            ImageIO.write(bi, imgSuffix, targetFile);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 获取视频时长，单位为秒
     * @param file
     * @return 时长（s）
     */
    public static Long getVideoTime(File file) {
        Long times = 0L;
        try {
            FFmpegFrameGrabber ff = new FFmpegFrameGrabber(file);
            ff.start();
            times = ff.getLengthInTime() / (1000 * 1000);
            ff.stop();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return times;
    }

    /**
     * 存入图片名称重复处理 工具类
     * @param file
     * @return
     */
    public static Integer getFileName(File file,int num){
        // 获得该文件夹内的所有文件
        File[] array = file.listFiles();
        ArrayList<Integer> list = new ArrayList<>();
        for(int i=0;i<array.length;i++) {
            if(array[i].isFile())//如果是文件
            {       //截取视频命名中的数字字符串并转化成数字类型
                list.add(Integer.parseInt(StringUtils.substring(array[i].getName(),2,array[i].getName().indexOf('.'))));
            }
        }
        //对list集合倒叙排序
        Collections.sort(list, Collections.reverseOrder());
        for (int i = 0; i < list.size(); i++){
            if(num == list.get(i)){
                num =  list.get(0) +1;
            }
        }
        return num;
    }
}
